using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace Win32SDK
{
    public sealed class Kernel32
    {
        public const string Dll = "kernel32.Dll";
        private Kernel32()
        {        
        }
        [DllImport(Kernel32.Dll, CharSet = CharSet.Unicode, ExactSpelling = true)]
        public static extern int WideCharToMultiByte(int codePage, int flags, [MarshalAs(UnmanagedType.LPWStr)] string wideStr, int chars, [In, Out] byte[] pOutBytes, int bufferBytes, IntPtr defaultChar, IntPtr pDefaultUsed);

        [DllImport(Kernel32.Dll, CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
        public static extern int MultiByteToWideChar(int CodePage, int dwFlags, byte[] lpMultiByteStr, int cchMultiByte, char[] lpWideCharStr, int cchWideChar);
        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto, SetLastError = true)]
        public static extern IntPtr LoadLibrary(string libname);
        [DllImport(Kernel32.Dll, EntryPoint = "MapViewOfFile", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        private static extern IntPtr IntMapViewOfFile(HandleRef hFileMapping, int dwDesiredAccess, int dwFileOffsetHigh, int dwFileOffsetLow, int dwNumberOfBytesToMap);
        [DllImport(Kernel32.Dll, EntryPoint = "UnmapViewOfFile", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        private static extern bool IntUnmapViewOfFile(HandleRef pvBaseAddress);
        [DllImport(Kernel32.Dll, EntryPoint = "DuplicateHandle", SetLastError = true, ExactSpelling = true)]
        private static extern IntPtr IntDuplicateHandle(HandleRef processSource, HandleRef handleSource, HandleRef processTarget, ref IntPtr handleTarget, int desiredAccess, bool inheritHandle, int options);
        [DllImport(Kernel32.Dll, EntryPoint = "CloseHandle", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        private static extern bool IntCloseHandle(HandleRef handle);
        [DllImport(Kernel32.Dll, EntryPoint = "CloseHandle", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        private static extern bool IntCloseHandle(IntPtr handle);

        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto, SetLastError = true)]
        public static extern short GlobalAddAtom(string atomName);
        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern IntPtr GlobalAlloc(int uFlags, int dwBytes);
        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern short GlobalDeleteAtom(short atom);
        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern IntPtr GlobalFree(HandleRef handle);
        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern IntPtr GlobalLock(HandleRef handle);
        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern IntPtr GlobalReAlloc(HandleRef handle, int bytes, int flags);
        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern int GlobalSize(HandleRef handle);
        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern bool GlobalUnlock(HandleRef handle);
        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern bool GetSystemPowerStatus([In, Out] ref SYSTEM_POWER_STATUS systemPowerStatus);
        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto)]
        public static extern void GetTempFileName(string tempDirName, string prefixName, int unique, StringBuilder sb);
        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto)]
        public static extern uint GetShortPathName(string lpszLongPath, StringBuilder lpszShortPath, uint cchBuffer);
        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto)]
        public static extern void GetStartupInfo([In, Out] STARTUPINFO_I startupinfo_i);
        [DllImport(Kernel32.Dll, CharSet = CharSet.Ansi, ExactSpelling = true)]
        public static extern IntPtr GetProcAddress(HandleRef hModule, string lpProcName);
        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto)]
        public static extern int GetModuleFileName(HandleRef hModule, StringBuilder buffer, int length);
        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto)]
        public static extern IntPtr GetModuleHandle(string modName);
        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto)]
        public static extern int GetLocaleInfo(int Locale, int LCType, StringBuilder lpLCData, int cchData);
        [DllImport(Kernel32.Dll)]
        public static extern bool GetExitCodeThread(IntPtr hThread, out uint lpExitCode);
        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto)]
        public static extern bool GetComputerName(StringBuilder lpBuffer, int[] nSize);
        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto)]
        public static extern bool FreeLibrary(HandleRef hModule);
        [DllImport(Kernel32.Dll, EntryPoint = "RtlMoveMemory", ExactSpelling = true)]
        public static extern void CopyMemory(IntPtr pdst, byte[] psrc, int cb);
        [DllImport(Kernel32.Dll, EntryPoint = "RtlMoveMemory", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        public static extern void CopyMemory(HandleRef destData, HandleRef srcData, int size);
        [DllImport(Kernel32.Dll, EntryPoint = "RtlMoveMemory", CharSet = CharSet.Ansi, ExactSpelling = true)]
        public static extern void CopyMemoryA(IntPtr pdst, string psrc, int cb);
        [DllImport(Kernel32.Dll, EntryPoint = "RtlMoveMemory", CharSet = CharSet.Ansi, ExactSpelling = true)]
        public static extern void CopyMemoryA(IntPtr pdst, char[] psrc, int cb);
        [DllImport(Kernel32.Dll, EntryPoint = "RtlMoveMemory", CharSet = CharSet.Unicode, ExactSpelling = true)]
        public static extern void CopyMemoryW(IntPtr pdst, char[] psrc, int cb);
        [DllImport(Kernel32.Dll, EntryPoint = "RtlMoveMemory", CharSet = CharSet.Unicode, ExactSpelling = true)]
        public static extern void CopyMemoryW(IntPtr pdst, string psrc, int cb);


        //[DllImport(Kernel32.Dll, CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        //public static extern bool CloseHandle(HandleRef handle);

        public static bool CloseHandle(HandleRef handle)
        {
            HandleCollector.Remove((IntPtr)handle, CommonHandles.Kernel);
            return IntCloseHandle(handle);
        }

        public static bool CloseHandle(IntPtr handle)
        {
            return IntCloseHandle(handle);
        }

        public static IntPtr DuplicateHandle(HandleRef processSource, HandleRef handleSource, HandleRef processTarget, ref IntPtr handleTarget, int desiredAccess, bool inheritHandle, int options)
        {
            IntPtr ptr = IntDuplicateHandle(processSource, handleSource, processTarget, ref handleTarget, desiredAccess, inheritHandle, options);
            HandleCollector.Add(handleTarget, CommonHandles.Kernel);
            return ptr;
        }
        public static IntPtr MapViewOfFile(HandleRef hFileMapping, int dwDesiredAccess, int dwFileOffsetHigh, int dwFileOffsetLow, int dwNumberOfBytesToMap)
        {
            return HandleCollector.Add(IntMapViewOfFile(hFileMapping, dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow, dwNumberOfBytesToMap), CommonHandles.Kernel);
        }
        public static bool UnmapViewOfFile(HandleRef pvBaseAddress)
        {
            HandleCollector.Remove((IntPtr)pvBaseAddress, CommonHandles.Kernel);
            return IntUnmapViewOfFile(pvBaseAddress);
        }

        [DllImport(Kernel32.Dll, ExactSpelling = true)]
        public static extern bool SetStdHandle(int nStdHandle, IntPtr hHandle);
        [DllImport(Kernel32.Dll, ExactSpelling = true)]
        public static extern IntPtr GetStdHandle(int nStdHandle);
        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto)]
        public static extern bool WriteConsole(IntPtr hConsoleOutput, string lpBuffer, uint nNumberOfCharsToWrite, ref uint lpNumberOfCharsWritten, IntPtr lpReserved);


        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto)]
        public static extern uint GetLastError();
        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto)]
        public static extern bool CreatePipe(out IntPtr hReadPipe, out IntPtr hWritePipe, IntPtr lpPipeAttributes, int nSize);

        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto)]
        public static extern bool ReadFile(IntPtr hFile, IntPtr lpBuffer, UInt32 nNumberOfBytesToRead, out UInt32 lpNumberOfBytesRead, [In]ref System.Threading.NativeOverlapped lpOverlapped);
        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto)]
        public static extern bool ReadFile(IntPtr hFile, IntPtr lpBuffer, UInt32 nNumberOfBytesToRead, out UInt32 lpNumberOfBytesRead, IntPtr lpOverlapped);
        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto)]
        public static extern bool WriteFile(IntPtr hFile, IntPtr lpBuffer, UInt32 nNumberOfBytesToWrite, out UInt32 lpNumberOfBytesWritten, [In]ref System.Threading.NativeOverlapped lpOverlapped);

        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto)]
        public static extern bool WriteFile(IntPtr hFile, IntPtr lpBuffer, UInt32 nNumberOfBytesToWrite, out UInt32 lpNumberOfBytesWritten, IntPtr lpOverlapped);

        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto)]
        public static extern bool ReadFileEx(IntPtr hFile, IntPtr lpBuffer, UInt32 nNumberOfBytesToRead, [In]ref System.Threading.NativeOverlapped lpOverlapped, FileIOCompletionRoutine lpCompletionRoutine);
        [DllImport(Kernel32.Dll, CharSet = CharSet.Auto)]
        public static extern bool ReadFileEx(IntPtr hFile, IntPtr lpBuffer, UInt32 nNumberOfBytesToRead, IntPtr lpOverlapped, FileIOCompletionRoutine lpCompletionRoutine);

        [DllImport(Kernel32.Dll)]
        public static extern bool SetCommTimeouts(IntPtr hFile, [In]ref COMMTIMEOUTS lpCommTimeouts);

        [DllImport(Kernel32.Dll)]
        public static extern bool GetCommTimeouts(IntPtr hFile, [Out]out COMMTIMEOUTS lpCommTimeouts);


        [DllImport(Kernel32.Dll)]
        public static extern int QueryPerformanceFrequency(out Int64 lpFrequency);

        [DllImport(Kernel32.Dll)]
        public static extern int QueryPerformanceCounter(out Int64 lpPerformanceCounter);

        private static Int64 performanceFrequency;

        public static Int64 PerformanceCounter
        {
            get
            {
                Int64 ret;
                QueryPerformanceCounter(out ret);
                return ret;
            }
        }
        public static Int64 PerformanceFrequency
        {
            get { return performanceFrequency; }
        }

        static Kernel32()
        {
            QueryPerformanceFrequency(out performanceFrequency);
        }
    }
}
